﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using Interfaces;
using Helpers;
using System.Windows.Controls;
using System.Windows.Input;
using System.IO;
using DataModel;
using System.Collections.ObjectModel;
using System.Windows;

namespace ImportPersons
{
    [Export(typeof(IModule))]
    [ModuleMetadata(Name = "Import users", Short = "userimport", Group = "Imports", IconFilename = "ImportPeople.png")]
    public class ImportPersonsViewModel : NotifyPropertyChangedBase, IModule
    {
        string _filename;
        public string Filename
        {
            get { return _filename; }
            set
            {
                _filename = value;
                NotifyPropertyChanged("Filename");
            }
        }

        ObservableCollection<Person> _persons;
        public ObservableCollection<Person> Persons
        {
            get { return _persons; }
            set
            {
                _persons = value;
                NotifyPropertyChanged("Persons");
            }
        }

        double _progressValue;
        public double ProgressValue
        {
            get { return _progressValue; }
            set
            {
                _progressValue = value;
                NotifyPropertyChanged("ProgressValue");
            }
        }

        Visibility _progressVisibility;
        public Visibility ProgressVisibility
        {
            get { return _progressVisibility; }
            set
            {
                _progressVisibility = value;
                NotifyPropertyChanged("ProgressVisibility");
            }
        }

        RelayCommand _importCommand;
        public ICommand ImportCommand
        {
            get
            {
                if (_importCommand == null)
                {
                    _importCommand = new RelayCommand(param => this.Import(), param => this.CanImport);
                }
                return _importCommand;
            }
        }

        public bool CanImport
        {
            get { return _filename != null && File.Exists(_filename); }
        }

        //Number;LastName;FirstName;Birthdate;Sex;Class;Birthplace;Street;Zip;City;Phone
        //1;Doe;John;31.12.2000;W;5B;Düsseldorf;Mannheimer Str. 51a;47890;Duisburg;(0211) 123456;

        public void Import()
        {
            StreamReader sr = new StreamReader(_filename, Encoding.Default);
            IEnumerable<string[]> data = sr.ReadToEnd().Replace("\r", "").Split('\n').Skip(1).Select(x => x.Split(';'));
            var persons = data.Where(x => x.Length > 2).Select(x => new
            {
                LastName = x[1],
                FirstName = x[2],
                Birthday = DateTime.Parse(x[3]),
                Sex = x[4],
                Class = ExtractClassFrom(x[5]),
                ClassId = ExtractClassIdFrom(x[5]),
                BirthPlace = x[6],
                Street = ExtractStreetFrom(x[7]),
                Housenumber = ExtractHouseNumberFrom(x[7]),
                Zip = x[8],
                City = x.Length > 9 ? x[9] : null,
                Phone = x.Length > 10 ? x[10] : null
            }).ToList();

            int SchoolYear = DateTime.Now.Year;
            if (DateTime.Now.Month < 8)
                SchoolYear--;

            ProgressValue = 0.0;
            ProgressVisibility = Visibility.Visible;
            DataLayer d = DataLayer.Data;
            int n = 0;
            foreach (var p in persons)
            {
                Address a = AddAddress(d, p.City, p.Zip, p.Street, p.Housenumber);

                Phone ph = AddPhone(d, PhoneType.Private, p.Phone);
                var s = new Student
                {
                    LastName = p.LastName,
                    FirstName = p.FirstName,
                    SexAsString = p.Sex,
                    ClassID = p.ClassId,
                    BirthPlace = p.BirthPlace,
                    StartYear = SchoolYear - p.Class + 5,
                    Delayed = 0,
                    StartedHere = SchoolYear - p.Class + 5,
                    ADDRESS = a,
                    Phones = new List<Phone>()
                };
                s.Phones.Add(ph);

                d.Persons.Add(s);
                d.SaveChanges();

                n++;
                ProgressValue = 1.0 * n / persons.Count();
            }
            ProgressVisibility = Visibility.Hidden;
            Persons = new ObservableCollection<Person>(d.Persons);
        }

        Address AddAddress(DataLayer d, string city, string zip, string street, string houseNumber)
        {
            Address a = d.Addresses
                        .Where(x => x.ZIP == zip
                            && x.Street.ToUpper() == street.ToUpper()
                            && x.Housenumber.ToUpper() == houseNumber.ToUpper()
                        )
                        .FirstOrDefault();

            if (a == null)
            {
                a = new Address
                {
                    City = city,
                    ZIP = zip,
                    Street = street,
                    Housenumber = houseNumber
                };
                d.Addresses.Add(a);
            }
            return a;
        }

        Phone AddPhone(DataLayer d, PhoneType type, string number)
        {
            Phone p = new Phone
            {
                PhoneType = type,
                Number = number
            };
            d.Phones.Add(p);
            return p;
        }

        int ExtractClassFrom(string s)
        {
            switch( s.ToUpper() )
            {
                case "EF":
                    return 10;
                case "Q1":
                    return 11;
                case "Q2":
                    return 12;
            }
            int i = 0;
            while (i < s.Length && Char.IsDigit(s[i]))
                i++;
            if (i < 1)
                return 0;
            return int.Parse(s.Substring(0, i));
        }

        string ExtractClassIdFrom(string s)
        {
            switch (s.ToUpper())
            {
                case "EF":
                    return "";
                case "Q1":
                    return "";
                case "Q2":
                    return "";
            }
            int i = 0;
            while (i < s.Length && Char.IsDigit(s[i]))
                i++;
            if (i < s.Length)
                return s.Substring(i);
            return "";
        }

        string ExtractStreetFrom(string s)
        {
            int p = s.LastIndexOf(' ');
            if (p > 0)
                return s.Substring(0, p);
            return s;
        }

        string ExtractHouseNumberFrom(string s)
        {
            int p = s.LastIndexOf(' ');
            if (p > 0)
                return s.Substring(p + 1);
            return "";
        }

        public UserControl View()
        {
            ProgressVisibility = Visibility.Hidden;
            var v = new ImportPersonsView();
            v.DataContext = this;
            return v;
        }
    }
}
